﻿using AIVision.InspectModule.Inspect;
using AIVision.InspectModule.Inspect.HCDL;
using AIVision.InspectModule.Inspect.Models;
using AIVision.MaoKe01.Application.Event;
using AIVision.MaoKe01.Application.Toolkit;
using AIVision.PhotoModule;
using HalconDotNet;
using HslCommunication;
using HslCommunication.ModBus;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AIVision.MaoKe01.Application
{
    public class MachineService
    {
        private readonly IEventAggregator eventAggregator;
        private CameraAgent cameraAgent;
        private ICheckUnit  checkUnit;
        private ModbusRtu modbusRtu;
        public MachineModel MachineModel { get; }
        InspectCfgModel inspectCfg;
        public MachineService(IEventAggregator eventAggregator, MachineModel machineModel)
        {
            this.eventAggregator = eventAggregator;
            MachineModel = machineModel;
        }

        public void Init()
        {
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("开始初始化相机...", 1));
            cameraAgent = new CameraAgent(new CameraCfgModel() { 
                Code="c01",
                Name="左相机",
                CameraHardKey= "44A6421ADADC"
            });
            try
            {
                cameraAgent.Init();
                MachineModel.CameraReady = true;
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"相机初始化成功！", 1));
            }
            catch (Exception ex)
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"相机初始化失败:{ex.Message}", 2));
                return;
            }
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("开始初始化深度学习模型...", 1));
            try
            {
                inspectCfg = XmlHelper.DeserializeFromXml<InspectCfgModel>("D:\\DLModels\\InspectCfg.xml");
            }
            catch (Exception ex)
            {
                LoadDefultInspectCfg();
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"读取配置文件错误:{ex.Message}，已使用默认配置", 2));
                return;
            }
            try
            {
                if (inspectCfg.InspectType == EnumInspectType.DL.ToString())
                    checkUnit = new DLCheckUnitInstance();
                if (checkUnit != null)
                {
                    checkUnit.Init(inspectCfg);
                    MachineModel.InspectUnitReady = true;
                }
                else
                {
                    throw new Exception($"checkUnit 未找到对应的实例");
                }
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"深度学习模型初始化成功！", 1));
            }
            catch (Exception ex)
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"深度学习初始化失败:{ex.Message}", 2));
                return;
            }
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("开始初始化串口通信...", 1));
            modbusRtu = new ModbusRtu();
            modbusRtu.SerialPortInni("COM1", 115200);
            OperateResult serialResult = modbusRtu.Open();
            if(serialResult.IsSuccess)
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("串口通信初始化成功", 1));
            }
            else
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"串口通信初始化失败:{serialResult.Message}", 2));
            }
        }
        public bool RunPhoto()
        {
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("开始触发拍照...", 1));
            string photoPath="", errMsg="";
            if(cameraAgent.TriggerPhoto(ref photoPath, ref errMsg))
            {
                MachineModel.SourcePhotoPath = photoPath;
                eventAggregator.GetEvent<SourceShowEvent>().Publish(photoPath);
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("拍照完成！", 1));
                return true;
            }
            else
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"拍照失败:{errMsg}", 1));
                return false;
            }
        }
        public bool RunInspect()
        {
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("开始深度学习检查...", 1));
            if (!File.Exists(MachineModel.SourcePhotoPath))
            {
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"缓存图片不存在!", 2));
                return false;
            }
            Stopwatch stopwatch = Stopwatch.StartNew();
            HObject currentImage = new HObject();
            HOperatorSet.ReadImage(out currentImage, MachineModel.SourcePhotoPath);
            InspectResultModel inspectResult = checkUnit.ExUnitCheck(currentImage);
            stopwatch.Stop();
            if (inspectResult.RunResult)
            {
                MachineModel.InspectImgPath = inspectResult.InspectImgPath;
                MachineModel.DefectImgPath = inspectResult.DefectImgPath;
                if (inspectResult.OKScore == inspectResult.Score)    //合格
                {
                    MachineModel.InspectPass = true;
                    eventAggregator.GetEvent<DefectShowEvent>().Publish(inspectResult.InspectImgPath);
                }
                else                                                                            //不合格，有不良
                {
                    MachineModel.InspectPass = false;
                    MachineModel.DefectNameSummary = inspectResult.DefectNameSummary;
                    eventAggregator.GetEvent<DefectShowEvent>().Publish(inspectResult.DefectImgPath);
                }
            }
            else                                                                         //不合格，中途有异常
            {
                MachineModel.InspectPass = false;
                MachineModel.DefectNameSummary = inspectResult.Message;


                if (!string.IsNullOrEmpty(inspectResult.DefectImgPath))
                    eventAggregator.GetEvent<DefectShowEvent>().Publish(inspectResult.DefectImgPath);
                else if (!string.IsNullOrEmpty(inspectResult.InspectImgPath))
                    eventAggregator.GetEvent<DefectShowEvent>().Publish(inspectResult.InspectImgPath);
                else
                    eventAggregator.GetEvent<DefectShowEvent>().Publish(MachineModel.SourcePhotoPath);
            }
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"深度学习检查完成,用时:{stopwatch.ElapsedMilliseconds}ms!", 1));
            return true;
        }
        public void ManualTriggerRun()
        {
            MachineModel.ManualTriggerFlag = true;

        }
        public void SwitchAutoRun()
        {
            if (MachineModel.AutoRunFlag)
            {
                MachineModel.AutoRunFlag = false;
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("停止自动运行!", 1));
            }
            else
            {
                MachineModel.AutoRunFlag = true;
                Task.Run(() => { AutoRun(); });
                eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs("启动自动运行!", 1));
            }
            
        }
        public void AutoRun()
        {
            while (MachineModel.AutoRunFlag)
            {
                bool runFlag = false;   //定义一个运行标志，无论手动或机器触发，只要运行标记为True，就触发拍照、检测、plc写入结果
                if (MachineModel.IsMachineTrigger)   //机器触发
                {
                   var result = modbusRtu.ReadInt16("100");
                    if(!result.IsSuccess)
                    {
                        eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"读取串口数据失败:{result.Message}", 1));
                        MachineModel.AutoRunFlag=false;
                    }

                    if(result.Content == 1)
                        runFlag = true;
                }
                else                                                      //手动触发模式
                {
                    if(MachineModel.ManualTriggerFlag)
                    {
                        MachineModel.ManualTriggerFlag = false;
                        runFlag = true;
                    }
                }
                if(runFlag)
                {
                    runFlag = false;
                    if (!RunPhoto())
                        return;
                    RunInspect();

                    //PLC写入结果
                }


            }
        }

        public void SaveInpsectCfg()
        {
            XmlHelper.SerializeToXml(inspectCfg, "D:\\DLModels\\InspectCfg.xml");
            eventAggregator.GetEvent<MessageEvent>().Publish(new MessageEventArgs($"配置存入:D:\\DLModels\\InspectCfg.xml", 1));
        }


        private void LoadDefultInspectCfg()
        {
            inspectCfg = new InspectCfgModel()
            {
                Code = "01",
                Name = "01",
                IsInspectOKImage = false,
                IsSaveDefectImage = false,
                ImageFileSavePath = "",
                ImageCache = true,
                InspectType = EnumInspectType.DL.ToString(),
                HCFilePath = "D:\\DLModels\\qiu\\DLScript.hdev",
                DLProcessFilePath = "D:\\DLModels\\qiu\\dl_preprocess_param.hdict",
                DLModelFilePath = "D:\\DLModels\\qiu\\best_dl_model_segmentation.hdl",
                DLDevice = "gpu",
                OKScore = 100
            };
            inspectCfg.DefectItems = new List<DefectItemModel>();
            inspectCfg.DefectItems.Add(new DefectItemModel()
            {
                AreaName = "All",
                AreaIndex = 1,
                DefectName = "黑气泡",
                DefectCode = "HQP",
                DefectIndex = 1,
                MinArea = 0,
                MinWidth = 0,
                MinHeight = 0,
                MaxStructFactor = 0
            });
        }
    }
}
